#!/usr/bin/perl
####################################################################
#   Project : tv_renamer
#        ID : $Id$
#   Purpose : Rename files using TV.com's database
#    Author : Grzegorz 'Jabbas' Dzięgielewski
####################################################################

use warnings;
use strict;

use Carp;
use Getopt::Long;
use Params::Validate qw/:all/;
use WWW::TV qw//;

# For debug only
use Data::Dumper;

# Getopt::Long stuff
my $opts;

my @result = Getopt::Long::GetOptions(
    'filename|n=s{,}'   => \@{$opts->{filename}},
    'format|f=s'        => \$opts->{format},
    'series_id|s=i'     => \$opts->{series_id},
    'help|h'            => sub { help_message() },
);

print Dumper validate_options($opts);

exit 0;

$opts->{format} = "%N %Sx%E - %n"   unless ($opts->{format});

print Dumper @ARGV; exit 0;
################################################################################

my $fn_opts = extract_from_filename({ filename => $opts->{filename} });
my @ep_data = get_season_episodes({ tv_series_id => $opts->{series_id}, season_no => $fn_opts->{season}, format => $opts->{format} });

my @current_episode_data = map { $_->{name} } grep { $_->{episode} == $fn_opts->{episode} } @ep_data;

die "I have ambiguous data, You need to rename this file manually:\n". join("\n", @current_episode_data) ."\n"  if scalar @current_episode_data != 1;

my $new_filename = $current_episode_data[0].".".$fn_opts->{extension};


change_name($new_filename, $opts->{filename});


#################### Internal functions
################################################################################
sub validate_options {
    my $opts = validate(@_,{
        'filename'  => {
            type        => ARRAYREF,
            optional    => 0
        },
        'format'    => {
            default     => "%N %Sx%E - %n",
        },
        'series_id' => {
            type        => SCALAR,
            regex       => qr/^\d+$/,
            optional    => 0
        },
        'help'      => {
            type        => BOOLEAN,
            optional    => 1
        }
    });
    
    return $opts;
}
sub change_name {
    my ($old_fn, $new_fn) = validate_pos(@_,
        { type  => SCALAR, optional => 0 },
        { type  => SCALAR, optional => 0 }
    );
    
    die "New and old filename are equal - leaving as is:\n$opts->{filename}" if ($new_fn eq $old_fn);
    
    print "Renaming '$opts->{filename}' to '$new_filename'\n";
#    rename $opts->{filename}, $new_filename;    
}

sub extract_from_filename {
    my $P = validate(@_, {
        'filename'  => {
            type        => SCALAR,
            required    => 1
        }
    });
    
    $P->{filename} =~ m/.*(\d{1,2}[ex]\d{1,2}).*\.(.*$)/i;
    
    my ($season, $episode, $ext) = split /[ex]/i, $1, 2;
    
    return { 'season' => int $season, 'episode' => int $episode, 'extension' => $2};
}

sub get_season_episodes {
    my $P = validate(@_, {
        'tv_series_id'      => {
            type        => SCALAR,
            optional    => 0
        },
        'season_no'         => {
            type        => SCALAR,
            optional    => 0
        },
        'format'    => {
            type        => SCALAR,
            optional    => 1
        }
    });
    
    my $series = WWW::TV::Series->new(id => $P->{'tv_series_id'});
    
    my @episodes_ids = map { $_->id } $series->episodes( season => $P->{'season_no'} );
    
    my @episodes;
    
    foreach my $ep_id (@episodes_ids) {
        my $episode = WWW::TV::Episode->new(id => $ep_id);
        
        $P->{'format'}  ? push @episodes, { 'name' => $episode->format_details($P->{'format'}), 'episode' => $episode->episode_number() } : push @episodes, $episode->id();
    }
    
    return sort { $a->{episode} <=> $b->{episode} } @episodes;
}

sub help_message {
    my $err = shift;
    
    $err    ? $err .="\n" : $err ="";

    $0 =~ s/.*\/(.*)$/$1/;

    print $err.<<END_HELP;
$0

usage: $0 [OPTIONS]

    -n, -filename   filename to rename",
    -f, -format     format of the destination file name, extension will be added automagically:
                        %I - series ID
                        %N - series name
                        %s - season number
                        %S - season number (0-padded to two digits, if required)
                        %i - episode ID
                        %e - episode number
                        %E - episide number (0-padded to two digits, if required)
                        %n - episode name
                        %d - date episode first aired

                        The default format is:
                            %N %Sx%E - %n (eg: "Heroes 01x02 - Don't Look Back")

    -s, -series_id      TV.com's series id (can be easily get from the URL,
    -h, -help           this message
END_HELP

exit 0;
}